<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2.极坐标-绘制更多曲线</title>
    <style>
        canvas{
            border:1px solid #aaa;
            margin: 0 auto;
            display: block;
        }
    </style>
</head>
<body>
    <canvas width="554" height="554"></canvas>
    <script src="/common/lib/gl-renderer.js"></script>
    <script type="module">
        import { loadImage, toPolar, fromPolar } from "/common/lib/utils.js";
        
        let canvas = document.querySelector("canvas");
        let ctx = canvas.getContext("2d")

        // 1.设置坐标，坐标变换
        ctx.translate(canvas.width/2, canvas.height/2);//将坐标原点平移到画布最底部
        ctx.scale(1,-1);//翻转y轴，让y轴朝上
        ctx.lineCap = 'round';// 定义线条末端线帽的样式
        
        // 根据点来绘制图形
        function draw(points, context, {
            strokeStyle = 'black',
            fillStyle = null,
            close = false,
        } = {}) {
            context.strokeStyle = strokeStyle;
            context.beginPath();
            context.moveTo(...points[0]);
            for(let i = 1; i < points.length; i++) {
                context.lineTo(...points[i]);
            }
            if(close) context.closePath();
            if(fillStyle) {
                context.fillStyle = fillStyle;
                context.fill();
            }
            context.stroke();
        }

        // 参数方程高阶函数
        function parametric(xFunc, yFunc, rFunc) {
            return function (start, end, seg = 100, ...args) {
                const points = [];
                for(let i = 0; i <= seg; i++) {
                    const p = i / seg;
                    const t = start * (1 - p) + end * p;
                    const x = xFunc(t, ...args); // 计算参数方程组的x
                    const y = yFunc(t, ...args);  // 计算参数方程组的y
                    if(rFunc)
                        // 转换坐标(其他坐标转换为直角坐标)
                        points.push(rFunc(x, y));
                    else
                        points.push([x, y]);
                }
                return {
                    draw: draw.bind(null, points),
                    points,
                };
            };
        }


        
        // 玫瑰线
        const rose = parametric(
            (t, a, k) => a * Math.cos(k * t),
            t => t,
            fromPolar,
        );

        rose(0, Math.PI, 100, 200, 5).draw(ctx, {strokeStyle: 'blue'});

        // 心形线
        const heart = parametric(
            (t, a) => a - a * Math.sin(t),
            t => t,
            fromPolar,
        );

        heart(0, 2 * Math.PI, 100, 100).draw(ctx, {strokeStyle: 'red'});

        // 双纽线
        const foliumRight = parametric(
            (t, a) => Math.sqrt(2 * a ** 2 * Math.cos(2 * t)),
            t => t,
            fromPolar,
        );

        const foliumLeft = parametric(
            (t, a) => -Math.sqrt(2 * a ** 2 * Math.cos(2 * t)),
            t => t,
            fromPolar,
        );

        foliumRight(-Math.PI / 4, Math.PI / 4, 100, 100).draw(ctx, {strokeStyle: 'green'});
        foliumLeft(-Math.PI / 4, Math.PI / 4, 100, 100).draw(ctx, {strokeStyle: 'green'});


    </script>
</body>
</html>